package ph.com.gs3.formalistics.presenter.fragements.workers;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.json.JSONException;

import ph.com.gs3.formalistics.global.constants.DocumentFilter;
import ph.com.gs3.formalistics.global.constants.StarMark;
import ph.com.gs3.formalistics.global.utilities.logging.FLLogger;
import ph.com.gs3.formalistics.model.facades.OutgoingActionDataWriter;
import ph.com.gs3.formalistics.model.facades.UsersDataWriter;
import ph.com.gs3.formalistics.model.ldao.DocumentsLDAO;
import ph.com.gs3.formalistics.model.ldao.FormsLDAO;
import ph.com.gs3.formalistics.model.ldao.OutgoingActionsLDAO;
import ph.com.gs3.formalistics.model.ldao.UserDocumentsLDAO;
import ph.com.gs3.formalistics.model.vo.business.User;
import ph.com.gs3.formalistics.model.vo.business.document.DisplayReadyAction;
import ph.com.gs3.formalistics.model.vo.business.document.DocumentSummary;
import ph.com.gs3.formalistics.model.vo.business.form.Form;
import ph.com.gs3.formalistics.model.vo.business.form.FormFieldData.InvalidFormFieldException;
import ph.com.gs3.formalistics.model.vo.parsers.DocumentDisplayItemParser;
import ph.com.gs3.formalistics.model.vo.view.DocumentDisplayItem;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;

public class MainWorkerFragment extends Fragment {

	public static final String TAG = MainWorkerFragment.class.getSimpleName();

	// Data Access Objects
	private FormsLDAO formsLDAO;
	private DocumentsLDAO documentsLDAO;
	private UserDocumentsLDAO userDocumentsLDAO;
	private OutgoingActionsLDAO outgoingActionsLDAO;

	private OutgoingActionDataWriter outgoingActionDataWriter;

	// Local Fields
	private User user;
	private Map<Integer, Form> formCache;

	public static enum FormSearchMode {
		NO_CACHE, CACHED
	};

	public static MainWorkerFragment createInstance(User user) {
		MainWorkerFragment instance = new MainWorkerFragment();
		instance.user = user;
		instance.formCache = new HashMap<>();

		return instance;
	}

	// Required empty parameter constructor
	public MainWorkerFragment() {}

	private void initializeDependencies() {

		Context context = getActivity();

		formsLDAO = new FormsLDAO(context);
		documentsLDAO = new DocumentsLDAO(context);
		userDocumentsLDAO = new UserDocumentsLDAO(context);
		outgoingActionsLDAO = new OutgoingActionsLDAO(context);

		outgoingActionDataWriter = new OutgoingActionDataWriter(context);

	}

	// ================================================================================
	// {{ Document Related Methods

	public int getAvailableDocumentCount() {

		int count = 0;

		documentsLDAO.open();
		try {
			count = userDocumentsLDAO.getUserDocumentsCount(user.getId());
		} finally {
			documentsLDAO.close();
		}

		return count;

	}

	public void changeDocumentStarMark(int documentId, int formId, StarMark starMark) {

		try {
			userDocumentsLDAO.open();
			userDocumentsLDAO.changeDocumentStarMark(documentId, starMark);
		} finally {
			userDocumentsLDAO.close();
		}

		outgoingActionDataWriter.saveStarMark(documentId, formId, starMark, user);

	}

	public List<DocumentDisplayItem> getDocuments(int formId, DocumentFilter filter) {

		List<DocumentSummary> documentSummaries = new ArrayList<>();
		List<DisplayReadyAction> displayReadyActions = new ArrayList<>();

		List<DocumentDisplayItem> documentDisplayItems = new ArrayList<>();

		if (filter == DocumentFilter.OUTGOING_DOCUMENTS) {
			try {
				outgoingActionsLDAO.open();
				displayReadyActions = outgoingActionsLDAO.getAllDisplayReadyOutgoingActions(user
				        .getId());

				for (DisplayReadyAction displayReadyAction : displayReadyActions) {
					documentDisplayItems.add(DocumentDisplayItemParser
					        .parseDisplayReadyAction(displayReadyAction));
				}
			} finally {
				outgoingActionsLDAO.close();
			}
		} else {

			try {
				documentsLDAO.open();
				documentSummaries = documentsLDAO.getUserDocumentSummaries(user.getId(), formId,
				        filter);

				for (DocumentSummary document : documentSummaries) {
					documentDisplayItems.add(DocumentDisplayItemParser.parseDocumentSummary(
					        document, user));
				}

			} catch (JSONException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
				documentsLDAO.close();
			}
		}

		return documentDisplayItems;

	}

	// ================================================================================
	// {{ Form Related Methods

	public List<Form> getCurrentCompanyForms() {

		int companyId = user.getCompany().getId();

		List<Form> forms = new ArrayList<>();

		formsLDAO.open();
		try {
			forms = formsLDAO.getCompanyForms(companyId);
		} catch (JSONException | InvalidFormFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			formsLDAO.close();
		}

		return forms;
	}

	/**
	 * Searches for forms on cached mode
	 * 
	 * @param server
	 * @param webId
	 * @return
	 */
	public Form getForm(int id) {
		return getForm(id, FormSearchMode.CACHED);
	}

	public Form getForm(int id, FormSearchMode searchMode) {

		Form form = null;

		if (formCache.containsKey(id) && searchMode == FormSearchMode.CACHED) {
			form = formCache.get(id);
		} else {
			formsLDAO.open();
			try {
				form = formsLDAO.getForm(id);
			} catch (JSONException | InvalidFormFieldException e) {
				e.printStackTrace();
			} finally {
				formsLDAO.close();
			}

			// Add the form to the cache
			formCache.put(id, form);
		}

		return form;

	}

	// }}

	public void logUserOut() {
		UsersDataWriter dataWriter = new UsersDataWriter(getActivity());
		dataWriter.deactivateCurrentlyActiveUser();
	}

	public User getCurrentUser() {
		return user;
	}

	// ========================================================================
	// Implementation Methods

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		FLLogger.d(TAG, "on create");

	}

	@Override
	public void onAttach(Activity activity) {
		super.onAttach(activity);

		FLLogger.d(TAG, "on attach");
		initializeDependencies();
		// register the activity as the mode change listener
		// try {
		//
		// } catch (ClassCastException e) {
		// throw new ClassCastException(activity.toString() +
		// " must implement ModeChangeListener");
		// }

	}

}
